/**
 * @file app_control.c
 * @brief 覆冰监测应用程序控制实现
 * @version 1.0
 * @date 2023-03-15
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <time.h>
#include <getopt.h>
#include <math.h>
#include <sys/stat.h>    // 添加sys/stat.h头文件以支持mkdir函数
#include <errno.h>       // 添加errno.h用于errno检查

#include "app_control.h"
#include "common_defs.h"
#include "system_utils.h"
#include "thread_utils.h"
#include "camera_utils.h"
#include "visual_monitor.h"
#include "stereo_monitor.h"
#include "image_process.h"
#include "uart_handler.h"
#include "uart_protocol.h"
#include "ice_calculation.h"
#include "simulation.h"
#include "data_fusion.h"

// 风速阈值 - 全局定义
const float HIGH_WIND_THRESHOLD = 15.0f; // 15m/s以上视为大风
const float EXTREME_WIND_THRESHOLD = 25.0f; // 25m/s以上视为极端大风

// 全局控制变量
SampleMode g_sample_mode = SAMPLE_MODE_REAL;
RunMode g_run_mode = RUN_MODE_FULL_SYSTEM;  // 默认为完整系统功能

// 添加记录覆冰厚度的全局变量，用于状态判断
float g_previous_ice_thickness = 0.0f;
// 从ice_calculation.c中引用，不在这里定义
extern float g_current_ice_thickness;

// 风险等级名称数组 - 全局定义
const char* risk_level_names[] = {"无风险", "低风险", "中等风险", "高风险", "极端风险"};

// 配置参数
AppConfig g_config;

// 数据保存
static FILE *g_data_file = NULL;
static uint32_t g_data_count = 0; // 修改为uint32_t，与后续使用统一

// 文件操作常量定义
#define FLUSH_INTERVAL_MS 10000        // 刷新间隔，10秒
#define FILE_CHECK_INTERVAL_MS 30000   // 文件检查间隔，30秒
#define MAX_RECORDS_PER_FILE 10000     // 每个文件最大记录数

// 程序启动时间
uint64_t g_program_start_time = 0;

static bool g_initialized = false;
static uint64_t g_last_flush_time = 0;
static uint64_t g_last_check_time = 0;
static bool g_data_header_written = false;

// 全局变量
volatile bool g_running = true;
int g_camera_capture_count = 3;  // 默认捕获3次图像

/**
 * @brief 设置默认配置
 */
void set_default_config(void) {
    // 默认设置采样间隔为2秒
    g_config.sampling_interval_ms = 2000;
    
    // 默认日志设置
    g_config.log_level = LOG_LEVEL_INFO;
    snprintf(g_config.log_file, MAX_PATH_LENGTH, "ice_monitor.log");
    
    // 默认启用所有功能
    g_config.enable_visual = true;
    g_config.enable_stereo = true;  // 修改：默认启用立体视觉
    g_config.enable_sensor = true;
    
    // 默认保存数据
    g_config.save_data = true;
    snprintf(g_config.data_dir, MAX_PATH_LENGTH, "data");
    
    // 默认启用摄像头时间同步
    g_config.sync_camera_time = true;
    
    // 设置摄像头认证信息
    // 400W摄像头
    strncpy(g_config.cam_400w_auth.ip, "192.168.1.60", sizeof(g_config.cam_400w_auth.ip) - 1);
    strncpy(g_config.cam_400w_auth.username, "admin", sizeof(g_config.cam_400w_auth.username) - 1);
    strncpy(g_config.cam_400w_auth.password, "hitmc401", sizeof(g_config.cam_400w_auth.password) - 1);
    g_config.cam_400w_auth.type = CAMERA_TYPE_400W;
    
    // 左800W摄像头
    strncpy(g_config.cam_800w_left_auth.ip, "192.168.1.64", sizeof(g_config.cam_800w_left_auth.ip) - 1);
    strncpy(g_config.cam_800w_left_auth.username, "admin", sizeof(g_config.cam_800w_left_auth.username) - 1);
    strncpy(g_config.cam_800w_left_auth.password, "hitmc401", sizeof(g_config.cam_800w_left_auth.password) - 1);
    g_config.cam_800w_left_auth.type = CAMERA_TYPE_800W;
    
    // 右800W摄像头
    strncpy(g_config.cam_800w_right_auth.ip, "192.168.1.65", sizeof(g_config.cam_800w_right_auth.ip) - 1);
    strncpy(g_config.cam_800w_right_auth.username, "admin", sizeof(g_config.cam_800w_right_auth.username) - 1);
    strncpy(g_config.cam_800w_right_auth.password, "hitmc401", sizeof(g_config.cam_800w_right_auth.password) - 1);
    g_config.cam_800w_right_auth.type = CAMERA_TYPE_800W;
    
    // 视觉监测配置 - 修改为400W摄像头的参数
    memset(&g_config.visual_config, 0, sizeof(VisualMonitorConfig));
    // 设置摄像头URL
    snprintf(g_config.visual_config.camera_url, sizeof(g_config.visual_config.camera_url), 
             "rtsp://admin:hitmc401@192.168.1.60:554/stream1");
    g_config.visual_config.width = 2560;  // 400W摄像头分辨率
    g_config.visual_config.height = 1440;
    g_config.visual_config.fps = 30;
    g_config.visual_config.timeout_ms = 5000;
    
    // 立体视觉配置 - 修改为800W摄像头的参数
    memset(&g_config.stereo_config, 0, sizeof(StereoMonitorConfig));
    snprintf(g_config.stereo_config.left_camera_url, sizeof(g_config.stereo_config.left_camera_url), 
             "rtsp://admin:hitmc401@192.168.1.64:554/stream1");
    snprintf(g_config.stereo_config.right_camera_url, sizeof(g_config.stereo_config.right_camera_url), 
             "rtsp://admin:hitmc401@192.168.1.65:554/stream1");
    g_config.stereo_config.width = 3840;  // 800W摄像头分辨率
    g_config.stereo_config.height = 2160;
    g_config.stereo_config.baseline = 150.0f;  // 基线距离，单位mm，增加基线提高远端测量精度
    g_config.stereo_config.focal_length = 8.0f;  // 焦距，单位mm，增加焦距提高远距离观测能力

    // 串口配置 - 修改为匹配UartConfig结构体成员
    memset(&g_config.uart_config, 0, sizeof(UartConfig));
    snprintf(g_config.uart_config.device, sizeof(g_config.uart_config.device), "/dev/ttyS0");
    g_config.uart_config.baud_rate = 115200;
    g_config.uart_config.device_fd = -1;
    g_config.uart_config.data_bits = 8;
    g_config.uart_config.stop_bits = 1;
    g_config.uart_config.parity = 'N';
    g_config.uart_config.timeout_ms = DEFAULT_TIMEOUT_MS;
    g_config.uart_config.retry_count = DEFAULT_RETRY_COUNT;
    g_config.uart_config.debug_mode = DEFAULT_DEBUG_MODE;
    
    // 线缆参数配置
    g_config.cable_params.diameter = 10.0f;    // 线缆直径，单位mm
    g_config.cable_params.span = 300.0f;       // 档距，单位m
    g_config.cable_params.tension_no_ice = 1000.0f;  // 无覆冰时的拉力值，单位N
}

/**
 * @brief 打印命令行帮助信息
 * 
 * @param program_name 程序名称
 */
void print_usage(const char *program_name) {
    printf("覆冰监测系统 v%s\n", ICE_MONITOR_VERSION);
    printf("用法: %s [选项]\n\n", program_name);
    printf("选项:\n");
    printf("  -h, --help                  显示此帮助信息并退出\n");
    printf("  -m, --mode=MODE             设置运行模式:\n");
    printf("                                0=退出, 5=模拟模式, 6=帮助, 7=混合模式, 10=三摄像头模式\n");
    printf("  -s, --sampling=MS           设置采样间隔，单位毫秒 (默认: 2000)\n");
    printf("  -l, --log-level=LEVEL       设置日志级别 (0=调试, 1=信息, 2=警告, 3=错误, 4=关闭)\n");
    printf("  -f, --log-file=FILE         设置日志文件路径 (默认: ice_monitor.log)\n");
    printf("  -v, --enable-visual[=0|1]   启用/禁用视觉检测(400W摄像头) (默认: 启用)\n");
    printf("  -e, --enable-stereo[=0|1]   启用/禁用立体视觉(双800W摄像头) (默认: 禁用)\n");
    printf("  -r, --enable-sensor[=0|1]   启用/禁用传感器 (默认: 启用)\n");
    printf("  -d, --data-dir=DIR          设置数据保存目录 (默认: data)\n");
    printf("  -S, --save-data[=0|1]       启用/禁用数据保存 (默认: 禁用)\n");
    printf("  -a, --simulation            启用纯模拟模式 (等同于 -m 5)\n");
    printf("  --hybrid                    启用混合模式，结合模拟数据和摄像头捕获 (等同于 -m 7)\n");
    printf("  --triple-camera[=N]         启用三摄像头模式，N为捕获次数，默认3次 (等同于 -m 10)\n");
    printf("  --visual-url=URL            设置400W摄像头RTSP URL\n");
    printf("  --visual-width=WIDTH        设置400W摄像头宽度\n");
    printf("  --visual-height=HEIGHT      设置400W摄像头高度\n");
    printf("  --left-camera-url=URL       设置左800W摄像头RTSP URL\n");
    printf("  --right-camera-url=URL      设置右800W摄像头RTSP URL\n");
    printf("  --stereo-width=WIDTH        设置双目摄像头宽度\n");
    printf("  --stereo-height=HEIGHT      设置双目摄像头高度\n");
    printf("  --baseline=MM               设置双目摄像头基线距离，单位mm\n");
    printf("  --focal-length=MM           设置双目摄像头焦距，单位mm\n");
    printf("  --uart-device=DEV           设置串口设备路径\n");
    printf("  --uart-baudrate=RATE        设置串口波特率\n");
    printf("  --cable-diameter=MM         设置线缆直径，单位mm (默认: 10.0)\n");
    printf("  --cable-span=M              设置档距，单位m (默认: 300.0)\n");
    printf("  --cable-tension=N           设置无覆冰拉力，单位N (默认: 1000.0)\n");
}

/**
 * @brief 解析命令行参数
 * 
 * @param argc 参数数量
 * @param argv 参数值数组
 * @return int 成功返回0，失败返回非0
 */
int parse_command_line(int argc, char *argv[]) {
    static struct option long_options[] = {
        {"help",            no_argument,       0, 'h'},
        {"mode",            required_argument, 0, 'm'},
        {"sampling",        required_argument, 0, 's'},
        {"log-level",       required_argument, 0, 'l'},
        {"log-file",        required_argument, 0, 'f'},
        {"enable-visual",   optional_argument, 0, 'v'},
        {"enable-stereo",   optional_argument, 0, 'e'},
        {"enable-sensor",   optional_argument, 0, 'r'},
        {"data-dir",        required_argument, 0, 'd'},
        {"save-data",       optional_argument, 0, 'S'},
        {"simulation",      no_argument,       0, 'a'},
        {"hybrid",          no_argument,       0, 253},
        {"triple-camera",   optional_argument, 0, 254},
        {"visual-url",      required_argument, 0, 200},
        {"visual-width",    required_argument, 0, 201},
        {"visual-height",   required_argument, 0, 202},
        {"left-camera-url", required_argument, 0, 220},
        {"right-camera-url",required_argument, 0, 221},
        {"stereo-width",    required_argument, 0, 222},
        {"stereo-height",   required_argument, 0, 223},
        {"baseline",        required_argument, 0, 224},
        {"focal-length",    required_argument, 0, 225},
        {"uart-device",     required_argument, 0, 230},
        {"uart-baudrate",   required_argument, 0, 231},
        {"cable-diameter",  required_argument, 0, 240},
        {"cable-span",      required_argument, 0, 241},
        {"cable-tension",   required_argument, 0, 242},
        {0, 0, 0, 0}
    };
    int option_index = 0;
    int c;
    
    while ((c = getopt_long(argc, argv, "hm:s:l:f:v::e::r::d:S::a", 
                            long_options, &option_index)) != -1) {
        switch (c) {
            case 'h':
                g_run_mode = RUN_MODE_HELP;
                return 0;
            case 'm':
                g_run_mode = (RunMode)atoi(optarg);
                
                // 检查运行模式是否有效
                if (g_run_mode != RUN_MODE_EXIT && 
                    g_run_mode != RUN_MODE_SIMULATION && 
                    g_run_mode != RUN_MODE_HELP && 
                    g_run_mode != RUN_MODE_HYBRID && 
                    g_run_mode != RUN_MODE_TRIPLE_CAMERA) {
                    printf("错误：无效的运行模式 %d\n", g_run_mode);
                    printf("只支持模式: 0=退出, 5=模拟模式, 6=帮助, 7=混合模式, 10=三摄像头模式\n");
                    return -1;
                }
                
                // 模式5和模式7都使用模拟数据
                if (g_run_mode == RUN_MODE_SIMULATION || g_run_mode == RUN_MODE_HYBRID) {
                    g_sample_mode = SAMPLE_MODE_SIMULATION;
                    if (g_run_mode == RUN_MODE_SIMULATION) {
                        log_message(LOG_LEVEL_INFO, "纯模拟模式(模式5)：启用模拟数据，不使用任何物理设备");
                    } else {
                        log_message(LOG_LEVEL_INFO, "混合模式(模式7)：启用模拟数据和三摄像头功能");
                    }
                }
                
                break;
            case 's':
                g_config.sampling_interval_ms = atoi(optarg);
                if (g_config.sampling_interval_ms < 500) {
                    g_config.sampling_interval_ms = 500;
                    printf("警告: 采样间隔设置过小，已调整为500毫秒\n");
                }
                break;
            case 'l':
                g_config.log_level = atoi(optarg);
                break;
            case 'f':
                strncpy(g_config.log_file, optarg, MAX_PATH_LENGTH - 1);
                g_config.log_file[MAX_PATH_LENGTH - 1] = '\0';
                break;
            case 'v':
                if (optarg) {
                    g_config.enable_visual = atoi(optarg) != 0;
                } else {
                    g_config.enable_visual = true;
                }
                break;
            case 'e':
                if (optarg) {
                    g_config.enable_stereo = atoi(optarg) != 0;
                } else {
                    g_config.enable_stereo = true;
                }
                break;
            case 'r':
                if (optarg) {
                    g_config.enable_sensor = atoi(optarg) != 0;
                } else {
                    g_config.enable_sensor = true;
                }
                break;
            case 'd':
                strncpy(g_config.data_dir, optarg, MAX_PATH_LENGTH - 1);
                g_config.data_dir[MAX_PATH_LENGTH - 1] = '\0';
                break;
            case 'S':
                if (optarg) {
                    g_config.save_data = atoi(optarg) != 0;
                } else {
                    g_config.save_data = true;
                }
                break;
            case 'a':
                g_sample_mode = SAMPLE_MODE_SIMULATION;
                g_run_mode = RUN_MODE_SIMULATION;
                log_message(LOG_LEVEL_INFO, "启用纯模拟模式，不使用图像处理和串口通信");
                break;
            case 253: // hybrid
                g_run_mode = RUN_MODE_HYBRID;
                g_sample_mode = SAMPLE_MODE_SIMULATION;
                g_config.enable_visual = true;
                g_config.enable_stereo = true;
                log_message(LOG_LEVEL_INFO, "启用混合模式，结合模拟数据和三摄像头功能");
                break;
            case 254: // triple-camera
                g_run_mode = RUN_MODE_TRIPLE_CAMERA;
                g_config.enable_visual = true;
                g_config.enable_stereo = true;
                g_camera_capture_count = 3; // 默认捕获3次
                if (optarg) {
                    g_camera_capture_count = atoi(optarg);
                    if (g_camera_capture_count < 0) {
                        g_camera_capture_count = -1; // 无限捕获
                    }
                }
                log_message(LOG_LEVEL_INFO, "启用三摄像头模式，计划捕获次数: %d", 
                          g_camera_capture_count < 0 ? 0 : g_camera_capture_count);
                break;
            case 200: // visual-url
                strncpy(g_config.visual_config.camera_url, optarg, sizeof(g_config.visual_config.camera_url) - 1);
                g_config.visual_config.camera_url[sizeof(g_config.visual_config.camera_url) - 1] = '\0';
                break;
            case 201: // visual-width
                g_config.visual_config.width = atoi(optarg);
                break;
            case 202: // visual-height
                g_config.visual_config.height = atoi(optarg);
                break;
            case 220: // left-camera-url
                strncpy(g_config.stereo_config.left_camera_url, optarg, sizeof(g_config.stereo_config.left_camera_url) - 1);
                g_config.stereo_config.left_camera_url[sizeof(g_config.stereo_config.left_camera_url) - 1] = '\0';
                break;
            case 221: // right-camera-url
                strncpy(g_config.stereo_config.right_camera_url, optarg, sizeof(g_config.stereo_config.right_camera_url) - 1);
                g_config.stereo_config.right_camera_url[sizeof(g_config.stereo_config.right_camera_url) - 1] = '\0';
                break;
            case 222: // stereo-width
                g_config.stereo_config.width = atoi(optarg);
                break;
            case 223: // stereo-height
                g_config.stereo_config.height = atoi(optarg);
                break;
            case 224: // baseline
                g_config.stereo_config.baseline = atof(optarg);
                break;
            case 225: // focal-length
                g_config.stereo_config.focal_length = atof(optarg);
                break;
            case 230: // uart-device
                strncpy(g_config.uart_config.device, optarg, MAX_PATH_LENGTH - 1);
                g_config.uart_config.device[MAX_PATH_LENGTH - 1] = '\0';
                break;
            case 231: // uart-baudrate
                g_config.uart_config.baud_rate = atoi(optarg);
                break;
            case 240: // cable-diameter
                g_config.cable_params.diameter = atof(optarg);
                break;
            case 241: // cable-span
                g_config.cable_params.span = atof(optarg);
                break;
            case 242: // cable-tension
                g_config.cable_params.tension_no_ice = atof(optarg);
                break;
            default:
                return -1;
        }
    }
    
    return 0;
}

/**
 * @brief 信号处理函数，用于接收退出信号
 * 
 * @param sig 信号值
 */
void signal_handler(int sig) {
    if (sig == SIGINT || sig == SIGTERM) {
        log_message(LOG_LEVEL_INFO, "接收到退出信号，程序即将退出");
        g_running = false;
    }
}

/**
 * @brief 应用程序系统初始化
 * 重命名以避免与system_utils.c中的init_system冲突
 * 
 * @return int 成功返回0，失败返回非0
 */
int app_init_system(void) {
    // 初始化系统工具
    if (init_system_utils(g_config.log_file, g_config.log_level) != 0) {
        fprintf(stderr, "初始化系统工具失败\n");
        return -1;
    }
    
    // 创建数据目录
    if (g_config.save_data) {
        // 使用mkdir创建目录（需根据平台进行修改）
        if (mkdir(g_config.data_dir, 0755) != 0) {
            // 如果目录已存在，不认为是错误
            if (errno != EEXIST) {
                log_message(LOG_LEVEL_ERROR, "创建数据目录失败: %s", g_config.data_dir);
                return -1;
            }
        }
    }
    
    // 打印系统信息
    log_message(LOG_LEVEL_INFO, "覆冰监测系统 v%s 启动", ICE_MONITOR_VERSION);
    log_message(LOG_LEVEL_INFO, "构建时间: %s %s", ICE_MONITOR_BUILD_DATE, ICE_MONITOR_BUILD_TIME);
    
    // 记录使用的模式
    if (g_run_mode == RUN_MODE_SIMULATION) {
        log_message(LOG_LEVEL_INFO, "运行模式: 纯模拟模式 (模式5)");
    } else if (g_run_mode == RUN_MODE_TRIPLE_CAMERA) {
        log_message(LOG_LEVEL_INFO, "运行模式: 三摄像头模式 (模式10)，将从3个摄像头获取图像");
    }
    
    // 初始化模拟模块
    if (g_sample_mode == SAMPLE_MODE_SIMULATION) {
        if (init_simulation() != 0) {
            log_message(LOG_LEVEL_ERROR, "初始化模拟模块失败");
            return -1;
        }
        log_message(LOG_LEVEL_INFO, "模拟模块初始化成功");
    }
    
    // 在纯模拟模式下，跳过摄像头时间同步和硬件初始化
    if (g_run_mode == RUN_MODE_SIMULATION) {
        log_message(LOG_LEVEL_INFO, "运行在纯模拟模式下，跳过硬件初始化");
    } else {
        // 同步摄像头时间（第一次使用摄像头时）
        if ((g_config.enable_visual || g_config.enable_stereo) && g_config.sync_camera_time) {
            log_message(LOG_LEVEL_INFO, "开始同步摄像头时间...");
            sync_all_cameras_time();
        }
    }
    
    // 初始化数据融合模块
    if (init_data_fusion() != 0) {
        log_message(LOG_LEVEL_ERROR, "初始化数据融合模块失败");
        return -1;
    }
    log_message(LOG_LEVEL_INFO, "数据融合模块初始化成功");
    
    // 初始化各个线程
    if (g_config.enable_sensor && 
        g_run_mode != RUN_MODE_SIMULATION &&  // 模式5下完全不启动任何设备线程
        g_run_mode != RUN_MODE_TRIPLE_CAMERA) {
        // 初始化UART通信
        if (init_uart_handler(&g_config.uart_config) != 0) {
            log_message(LOG_LEVEL_ERROR, "初始化UART通信失败");
            return -1;
        }
    }
    
    return 0;
}

/**
 * @brief 系统清理
 */
void cleanup_system(void) {
    static bool already_cleaned = false;
    
    // 防止重复调用清理
    if (already_cleaned) {
        log_message(LOG_LEVEL_INFO, "系统资源已经清理，跳过重复清理");
        return;
    }
    
    already_cleaned = true;
    
    log_message(LOG_LEVEL_INFO, "系统正在清理资源...");
    
    // 判断是否为纯模拟模式
    bool pure_sim_mode = (g_sample_mode == SAMPLE_MODE_SIMULATION && g_run_mode == RUN_MODE_SIMULATION);
    
    // 清理数据融合模块
    cleanup_data_fusion();
    
    // 如果使用了模拟模式，清理模拟模块
    if (g_sample_mode == SAMPLE_MODE_SIMULATION) {
        cleanup_simulation();
    }
    
    // 纯模拟模式下跳过硬件资源清理
    if (!pure_sim_mode) {
        // 停止所有监测线程
        if (g_config.enable_visual) {
            stop_visual_monitor_thread();
            cleanup_visual_monitor();
        }
        
        if (g_config.enable_stereo) {
            stop_stereo_monitor_thread();
            cleanup_stereo_monitor();
        }
        
        // 清理图像处理
        cleanup_image_process();

        if (g_config.enable_sensor) {
            // 关闭串口
            if (g_config.uart_config.device_fd > 0) {
                close_uart(g_config.uart_config.device_fd);
                g_config.uart_config.device_fd = -1; // 标记为已关闭
            }
        }
    }
    
    // 关闭数据文件
    if (g_data_file) {
        fclose(g_data_file);
        g_data_file = NULL;
        log_message(LOG_LEVEL_INFO, "数据记录已完成，共记录 %lu 条数据", g_data_count);
    }
    
    // 清理系统工具
    cleanup_system_utils();
    
    log_message(LOG_LEVEL_INFO, "系统资源已清理");
}

/**
 * @brief 保存融合数据
 * 
 * @param data 融合数据指针
 */
void save_fusion_data(const FusionData* data) {
    static char data_dir[MAX_PATH_LENGTH] = {0};
    static char date_dir[MAX_PATH_LENGTH] = {0};
    static char data_file[MAX_PATH_LENGTH] = {0};
    static char temp_file[MAX_PATH_LENGTH] = {0};
    
    uint64_t current_time = get_timestamp_ms();
    bool need_new_file = false;
    int ret = 0;
    
    if (!data) {
        log_message(LOG_LEVEL_ERROR, "传入的数据为空，无法保存");
        return;
    }
    
    // 如果未初始化，则初始化文件路径
    if (!g_initialized) {
        // 锁定互斥锁以保护初始化过程
        lock_global_mutex(MUTEX_FILE_ACCESS);
        
        // 获取当前时间，用于生成文件名
        time_t now = time(NULL);
        struct tm tm_now;
        
        // 使用平台特定的函数获取本地时间
        #ifdef _WIN32
            localtime_s(&tm_now, &now);
        #else
            localtime_r(&now, &tm_now);
        #endif
        
        // 确保数据目录存在
        if (strlen(g_config.data_dir) > 0) {
            strncpy(data_dir, g_config.data_dir, sizeof(data_dir) - 1);
            data_dir[sizeof(data_dir) - 1] = '\0';
        } else {
            strncpy(data_dir, "data", sizeof(data_dir) - 1);
            data_dir[sizeof(data_dir) - 1] = '\0';
        }
        
        // 创建数据目录及子目录
        if (create_directory(data_dir) != 0) {
            log_message(LOG_LEVEL_ERROR, "创建数据目录失败: %s", data_dir);
            unlock_global_mutex(MUTEX_FILE_ACCESS);
            return;
        }
        
        // 创建日期子目录 (格式: data/YYYY-MM-DD/)
        int year = tm_now.tm_year + 1900;
        if (year < 0) year = 0; // 防止负数年份
        if (year > 9999) year = 9999; // 限制最大年份

        int ret = snprintf(date_dir, sizeof(date_dir), "%s/%04d-%02d-%02d", 
                data_dir, 
                year,  // 使用范围限制的年份 
                (tm_now.tm_mon + 1) % 13,  // 确保月份在1-12范围内
                tm_now.tm_mday % 32);      // 确保日期在1-31范围内

        // 检查是否有截断
        if (ret < 0 || ret >= sizeof(date_dir)) {
            log_message(LOG_LEVEL_ERROR, "日期目录路径太长，可能被截断: %s", date_dir);
            unlock_global_mutex(MUTEX_FILE_ACCESS);
            return;
        }
        
        // 创建日期子目录
        if (create_directory(date_dir) != 0) {
            log_message(LOG_LEVEL_ERROR, "创建日期子目录失败: %s", date_dir);
            unlock_global_mutex(MUTEX_FILE_ACCESS);
            return;
        }
        
        // 生成数据文件名 (格式: data/YYYY-MM-DD/ice_data_HHMMSS.csv)
        ret = snprintf(data_file, sizeof(data_file), "%s/ice_data_%02d%02d%02d.csv", 
                date_dir, tm_now.tm_hour, tm_now.tm_min, tm_now.tm_sec);
        
        // 检查是否有截断
        if (ret < 0 || ret >= sizeof(data_file)) {
            log_message(LOG_LEVEL_ERROR, "文件路径太长，可能被截断: %s", data_file);
            unlock_global_mutex(MUTEX_FILE_ACCESS);
            return;
        }
        
        // 生成临时文件名
        ret = snprintf(temp_file, sizeof(temp_file), "%s.tmp", data_file);
        
        // 检查是否有截断
        if (ret < 0 || ret >= sizeof(temp_file)) {
            log_message(LOG_LEVEL_ERROR, "临时文件路径太长，可能被截断: %s", temp_file);
            unlock_global_mutex(MUTEX_FILE_ACCESS);
            return;
        }
        
        // 设置标志，避免重复检查
        g_initialized = true;
        g_data_header_written = false;
        g_last_flush_time = get_timestamp_ms();
        g_last_check_time = g_last_flush_time;
        
        unlock_global_mutex(MUTEX_FILE_ACCESS);
    }
    
    // 锁定文件访问互斥锁
    lock_global_mutex(MUTEX_FILE_ACCESS);
    
    // 检查文件是否需要重新打开
    
    // 定期检查文件健康状态
    if (current_time - g_last_check_time > FILE_CHECK_INTERVAL_MS) {
        if (g_data_file) {
            // 检查文件描述符是否有效
            if (ferror(g_data_file)) {
                log_message(LOG_LEVEL_ERROR, "数据文件错误，将重新打开文件");
                fclose(g_data_file);
                g_data_file = NULL;
            }
            // 检查数据记录数是否达到上限
            else if (g_data_count >= MAX_RECORDS_PER_FILE) {
                log_message(LOG_LEVEL_INFO, "数据文件记录数达到上限，将创建新文件");
                fclose(g_data_file);
                g_data_file = NULL;
                need_new_file = true;
            }
        }
        g_last_check_time = current_time;
    }
    
    // 如果需要创建新文件
    if (need_new_file) {
        // 获取当前时间，用于生成新文件名
        time_t now = time(NULL);
        struct tm tm_now;
        
        #ifdef _WIN32
            localtime_s(&tm_now, &now);
        #else
            localtime_r(&now, &tm_now);
        #endif
        
        // 创建日期子目录 (格式: data/YYYY-MM-DD/)
        int year = tm_now.tm_year + 1900;
        if (year < 0) year = 0; // 防止负数年份
        if (year > 9999) year = 9999; // 限制最大年份

        ret = snprintf(date_dir, sizeof(date_dir), "%s/%04d-%02d-%02d", 
                data_dir, 
                year,  // 使用范围限制的年份
                (tm_now.tm_mon + 1) % 13,  // 确保月份在1-12范围内
                tm_now.tm_mday % 32);      // 确保日期在1-31范围内

        // 检查是否有截断
        if (ret < 0 || ret >= sizeof(date_dir)) {
            log_message(LOG_LEVEL_ERROR, "日期目录路径太长，可能被截断: %s", date_dir);
            unlock_global_mutex(MUTEX_FILE_ACCESS);
            return;
        }
        
        // 创建日期子目录
        if (create_directory(date_dir) != 0) {
            log_message(LOG_LEVEL_ERROR, "创建日期子目录失败: %s", date_dir);
            unlock_global_mutex(MUTEX_FILE_ACCESS);
            return;
        }
        
        // 生成新的数据文件名
        ret = snprintf(data_file, sizeof(data_file), "%s/ice_data_%02d%02d%02d.csv", 
                date_dir, tm_now.tm_hour, tm_now.tm_min, tm_now.tm_sec);
        
        // 检查是否有截断
        if (ret < 0 || ret >= sizeof(data_file)) {
            log_message(LOG_LEVEL_ERROR, "文件路径太长，可能被截断: %s", data_file);
            unlock_global_mutex(MUTEX_FILE_ACCESS);
            return;
        }
        
        // 生成新的临时文件名
        ret = snprintf(temp_file, sizeof(temp_file), "%s.tmp", data_file);
        
        // 检查是否有截断
        if (ret < 0 || ret >= sizeof(temp_file)) {
            log_message(LOG_LEVEL_ERROR, "临时文件路径太长，可能被截断: %s", temp_file);
            unlock_global_mutex(MUTEX_FILE_ACCESS);
            return;
        }
        
        // 重置标志
        g_data_header_written = false;
        g_data_count = 0;
    }
    
    // 如果文件未打开，则打开文件
    if (!g_data_file) {
        g_data_file = fopen(temp_file, "w");
        if (!g_data_file) {
            log_message(LOG_LEVEL_ERROR, "无法打开数据文件: %s, 错误: %s", 
                      temp_file, strerror(errno));
            unlock_global_mutex(MUTEX_FILE_ACCESS);
            return;
        }
        
        // 重置记录计数
        g_data_count = 0;
        g_data_header_written = false;
    }
    
    // 写入CSV头
    if (!g_data_header_written) {
        fprintf(g_data_file, "时间戳,厚度(mm),温度(℃),湿度(%%),风速(m/s),风向(°),"
                           "拉力(N),冰密度(kg/m³),冰重(kg/m),视觉厚度(mm),立体厚度(mm),风险等级,数据校验\n");
        g_data_header_written = true;
    }
    
    // 获取本地时间
    time_t timestamp_sec = data->timestamp / 1000;
    struct tm tm_info;
    
    #ifdef _WIN32
        localtime_s(&tm_info, &timestamp_sec);
    #else
        localtime_r(&timestamp_sec, &tm_info);
    #endif
    
    char time_str[32];
    strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", &tm_info);
    
    // 计算简单的数据校验和
    uint8_t checksum = 0;
    const uint8_t *data_bytes = (const uint8_t *)data;
    for (size_t i = 0; i < sizeof(FusionData); i++) {
        checksum ^= data_bytes[i];
    }
    
    // 写入数据记录
    fprintf(g_data_file, "%s,%0.2f,%0.1f,%0.1f,%0.1f,%0.1f,%0.1f,%0.1f,%0.3f,%0.2f,%0.2f,%d,%02X\n",
            time_str,
            g_current_ice_thickness,
            data->temperature,
            data->humidity,
            data->wind_speed,
            data->wind_direction,
            data->sensor_tension,
            data->ice_density,
            data->ice_weight,
            data->visual_thickness,
            data->stereo_thickness,
            data->risk_level,
            checksum);
    
    // 增加记录计数
    g_data_count++;
    
    // 定期刷新文件缓冲区
    if (current_time - g_last_flush_time > FLUSH_INTERVAL_MS) {
        fflush(g_data_file);
        
        // 使用fsync确保数据写入磁盘（仅在非Windows系统）
        #ifndef _WIN32
            int fd = fileno(g_data_file);
            if (fd >= 0) {
                fsync(fd);
            }
        #endif
        
        // 使用原子重命名操作，确保文件完整性
        fclose(g_data_file);
        if (rename(temp_file, data_file) != 0) {
            log_message(LOG_LEVEL_ERROR, "重命名临时文件失败: %s -> %s, 错误: %s", 
                      temp_file, data_file, strerror(errno));
        }
        
        // 重新打开临时文件继续写入
        g_data_file = fopen(temp_file, "w");
        if (!g_data_file) {
            log_message(LOG_LEVEL_ERROR, "刷新后无法重新打开数据文件: %s, 错误: %s", 
                      temp_file, strerror(errno));
            unlock_global_mutex(MUTEX_FILE_ACCESS);
            return;
        }
        
        // 重新写入CSV头
        fprintf(g_data_file, "时间戳,厚度(mm),温度(℃),湿度(%%),风速(m/s),风向(°),"
                          "拉力(N),冰密度(kg/m³),冰重(kg/m),视觉厚度(mm),立体厚度(mm),风险等级,数据校验\n");
        
        g_last_flush_time = current_time;
    }
    
    unlock_global_mutex(MUTEX_FILE_ACCESS);
}

int sync_all_cameras_time(void) {
    int ret = 0;
    
    // 初始化curl库
    if (init_curl_library() != 0) {
        log_message(LOG_LEVEL_ERROR, "无法初始化curl库，摄像头时间同步失败");
        return -1;
    }
    
    // 同步400W摄像头时间
    if (g_config.enable_visual) {
        log_message(LOG_LEVEL_INFO, "同步400W摄像头(%s)时间...", g_config.cam_400w_auth.ip);
        if (sync_camera_time((const CameraAuthInfo *)&g_config.cam_400w_auth) != 0) {
            log_message(LOG_LEVEL_WARNING, "400W摄像头时间同步失败，将在下次尝试");
            ret = -1;
        }
    }
    
    // 同步800W摄像头时间
    if (g_config.enable_stereo) {
        log_message(LOG_LEVEL_INFO, "同步左800W摄像头(%s)时间...", g_config.cam_800w_left_auth.ip);
        if (sync_camera_time((const CameraAuthInfo *)&g_config.cam_800w_left_auth) != 0) {
            log_message(LOG_LEVEL_WARNING, "800W左摄像头时间同步失败，将在下次尝试");
            ret = -1;
        }
        
        log_message(LOG_LEVEL_INFO, "同步右800W摄像头(%s)时间...", g_config.cam_800w_right_auth.ip);
        if (sync_camera_time((const CameraAuthInfo *)&g_config.cam_800w_right_auth) != 0) {
            log_message(LOG_LEVEL_WARNING, "800W右摄像头时间同步失败，将在下次尝试");
            ret = -1;
        }
    }
    
    // 清理curl库
    cleanup_curl_library();
    
    return ret;
}

// 删除与simulation.c中重复的convert_simulation_sensor_data函数
// 此函数已在simulation.c中实现 